#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>
#include <QDebug>
#include <QRadioButton>
#include <QtMath>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //绑定点选事件
    for(QRadioButton *bt:ui->groupBox->findChildren<QRadioButton*>()){
        connect(bt,&QRadioButton::clicked,this,&Widget::checkWho);
    }
    //设置画布大小与格式(带透明度的32位RGB彩色图)
    image = QImage(1920,1080,QImage::Format_ARGB32);
    //填充成透明颜色
    image.fill(QColor(0,0,0,0));
    penColor = QColor(255,0,0);    //设置画笔基础颜色
    penWidth = 3;                  //设置画笔宽度
}

Widget::~Widget()
{
    delete ui;
}

bool Widget::event(QEvent *event)
{
    QMouseEvent *e = static_cast<QMouseEvent*>(event);

    if(event->type()==QEvent::MouseButtonPress){
        QPoint press = e->pos();
        first = last = press;

        path = QPainterPath(first);             // 落笔处(落笔点)
        shapeAndPath shapePath(num,path);       // 创建一个封装了 图形形状 和 图形路径 的类
        paths.push(shapePath);                  // 将上面的类加入到绘画栈中

        pressedshapeAndPathIndex=0;
        for(shapeAndPath& sp:paths){
            if(sp.value().controlPointRect().contains(press) && sp.key()!=5)
                break;
            pressedshapeAndPathIndex++;
        }
    }
    else if(event->type()==QEvent::MouseMove){
        before = last;                          //往后移 保持记录倒数第二个点
        last = e->pos();                        //往后移 保持记录最后一个点
        if(pressedshapeAndPathIndex<paths.size()-1){
            paths[pressedshapeAndPathIndex].value().translate(last-before);
        }
        else
            Widget::fixFinalPath(num,path);     //确定最终的图形 num表示图形样式 path为图形路径
        update();
    }
    else if(event->type()==QEvent::MouseButtonRelease){
        qDebug()<<path.length();
        if(pressedshapeAndPathIndex>=paths.size()-1){
            if(!paths.isEmpty()) {
                if(num!=5)
                    Widget::drawPathtoDevice(&image,path);
                else
                    Widget::eraserPathfromDevice(&image,path);
                if(num<4){                      //基础图形是直接换成path
                    paths.last().value()=path;
                } else {                        //路径图形要加上之前的path
                    paths.last().value().addPath(path);
                    pointsNum = 1;
                }
            }
            path.clear();                       //松笔，代表图形已确定，清空临时path
            QPoint size = last-first;           //点击与松开的间隔太小时，视作失误点击，撤销操作
            if((abs(size.x())<7&&abs(size.y())<7&&num<4)) paths.pop_back();
        } else {
            Widget::repaintImage();
            paths.pop_back();
        }

        update();
    }
    if(event->type()==QEvent::Paint){
        painter.begin(this);
        painter.drawImage(0,0,image);           //先画已经确定的image图
        painter.end();
        if(!path.isEmpty())                     //再画当前正在确定的path （画在主界面上）
        {
            if(num!=5)
                drawPathtoDevice(this,path);
            else
                eraserPathfromDevice(this,path);
        }
        if(pressedshapeAndPathIndex<paths.size()){
            penColor = QColor(0,255,0);
            drawPathtoDevice(this,paths[pressedshapeAndPathIndex].value());
            penColor = QColor(255,0,0);
        }
    }
    return QWidget::event(event);
}

void Widget::checkWho()
{
    this->num = ((QRadioButton*)QObject::sender())->whatsThis().toInt();
    qDebug()<<num;
}

void Widget::setPenStyle(const QColor &color, int width)
{
    QPen pen(color);
    pen.setWidth(width);
    painter.setPen(pen);
    painter.setRenderHint(QPainter::Antialiasing, true);
}

void Widget::on_pushButton_clicked()
{
    if(!paths.isEmpty())            //删除最后一条路径
        paths.pop_back();
    Widget::repaintImage();
}

void Widget::drawPathtoDevice(QPaintDevice *device,QPainterPath &path)
{
    painter.begin(device);
    Widget::setPenStyle(penColor,penWidth);
    painter.drawPath(path);
    painter.end();
}

void Widget::fixFinalPath(int num,QPainterPath &path)
{
    switch (num) {
    case 1:
        path.clear();
        path.addRect(QRect(first,last).normalized());
        break;
    case 2:
        path.clear();
        path.addEllipse(QRect(first,last).normalized());
        break;
    case 3:
        path.clear();
        path = QPainterPath(first);
        path.lineTo(last);
        break;
    case 4: //既然画笔工具时 鼠标路径就是最终路径，为什么直接把路径画到Image里，而还要用path存储？
            //那是因为撤回功能，撤回需要知道撤回哪个路径，所以必须记录路径不可。
        path.lineTo(last);  //记录在路径中
        pointsNum++;        //记录点的次数+1
        if(pointsNum>255){  //每个路径记录了255个任意路径后便清零，保持绘画效率
            drawPathtoDevice(&image,path);  //记录满了便直接把路径画入 image同时清空临时路径path
            paths.last().value().addPath(path); //添加到栈顶路径中
            path.clear();
            path = QPainterPath(last);      //重新定位到最后一个点，继续画
            pointsNum=1;                    //重新记录点个数
        }
        break;
    case 5:
        path.lineTo(last);  //记录在路径中
        pointsNum++;        //记录点的次数+1
        if(pointsNum>511){  //每个路径记录了255个任意路径后便清零，保持绘画效率
            eraserPathfromDevice(&image,path);  //记录满了便直接把路径画入 image同时清空临时路径path
            paths.last().value().addPath(path); //添加到栈顶路径中
            path.clear();
            path = QPainterPath(last);      //重新定位到最后一个点，继续画
            pointsNum=1;                    //重新记录点个数
        }
       break;
    }
}

void Widget::repaintImage()
{
    image.fill(QColor(0,0,0,0));    //清空图片
    //再把记录的所有路径重新画到image上
    for(auto &m:paths){
        if(m.key()!=5)
            drawPathtoDevice(&image,m.value());
        else
            eraserPathfromDevice(&image,m.value());
    }
    update();
}

void Widget::eraserPathfromDevice(QPaintDevice *device,QPainterPath &path)
{
    painter.begin(device);
    painter.setCompositionMode(QPainter::CompositionMode_Clear);
    Widget::setPenStyle(QColor(),20);
    painter.drawPath(path);
    painter.end();
}
